// hwinpropsys.h

#pragma once
#ifndef __HWINPROPSYS_H__
#define __HWINPROPSYS_H__

#include "hwindef.h"
#include "hwincom.h"
#include "hwinexception.h"
#include "hwinvariant.h"
#include "hwinobj.h"


namespace harlinn
{
    namespace windows
    {
        class InitializeWithFile : public Unknown
        {
        public:
            typedef Unknown Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(InitializeWithFile,Unknown,IInitializeWithFile,IUnknown)

            InitializeWithFile& Initialize( LPCWSTR pszFilePath, DWORD grfMode)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->Initialize( pszFilePath, grfMode);
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
        
        };

        class InitializeWithStream : public Unknown
        {
        public:
            typedef Unknown Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(InitializeWithStream,Unknown,IInitializeWithStream,IUnknown)

            InitializeWithStream& Initialize( IStream *pstream,DWORD grfMode)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->Initialize( pstream, grfMode);
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
        };

        class PropertyStore : public Unknown
        {
        public:
            typedef Unknown Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(PropertyStore,Unknown,IPropertyStore,IUnknown)

            DWORD GetCount( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                DWORD result = 0;
                auto hr = pInterface->GetCount( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
        
            PropertyStore& GetAt(DWORD iProp, PROPERTYKEY *thekey)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->GetAt( iProp, thekey );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
            PropertyStore& GetAt(DWORD iProp, PROPERTYKEY& thekey)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->GetAt( iProp, &thekey );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
            PROPERTYKEY GetAt(DWORD iProp)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                PROPERTYKEY result = {0,};
                auto hr = pInterface->GetAt( iProp, &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
            PropertyVariant GetValue(REFPROPERTYKEY key)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                PropertyVariant result;
                auto hr = pInterface->GetValue( key, &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
            PropertyVariant GetValue(DWORD iProp)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                REFPROPERTYKEY key = GetAt(iProp);
                PropertyVariant result;
                auto hr = pInterface->GetValue( key, &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
        
            PropertyStore& SetValue( REFPROPERTYKEY key, REFPROPVARIANT propvar)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->SetValue( key, propvar );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
            PropertyStore& SetValue( REFPROPERTYKEY key, const PropertyVariant& propvar)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->SetValue( key, propvar );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
        
            PropertyStore& Commit( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->Commit( );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
        };


        class NamedPropertyStore : public Unknown
        {
        public:
            typedef Unknown Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(NamedPropertyStore,Unknown,INamedPropertyStore,IUnknown)

            PropertyVariant GetNamedValue( LPCWSTR pszName )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                PropertyVariant result;
                auto hr = pInterface->GetNamedValue( pszName, &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
        
            NamedPropertyStore& SetNamedValue( LPCWSTR pszName, REFPROPVARIANT propvar)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->SetNamedValue( pszName, propvar );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
        
            DWORD GetNameCount( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                DWORD result = 0;
                auto hr = pInterface->GetNameCount( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
        
            String GetNameAt(DWORD iProp)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                BSTR result = 0;
                auto hr = pInterface->GetNameAt(iProp, &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                String s(result,String::size_type(SysStringLen(result)));
                SysFreeString(result);
                return s;
            }
        
        };


        class ObjectWithPropertyKey : public Unknown
        {
        public:
            typedef Unknown Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(ObjectWithPropertyKey,Unknown,IObjectWithPropertyKey,IUnknown)

            ObjectWithPropertyKey& SetPropertyKey( REFPROPERTYKEY key )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->SetPropertyKey( key );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }

            PROPERTYKEY GetPropertyKey( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                PROPERTYKEY result = {0,};
                auto hr = pInterface->GetPropertyKey( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }

            ObjectWithPropertyKey& GetPropertyKey( PROPERTYKEY* theKey )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->GetPropertyKey( theKey );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }

            ObjectWithPropertyKey& GetPropertyKey( PROPERTYKEY& theKey )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->GetPropertyKey( &theKey );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
        };


        class PropertyChange : public ObjectWithPropertyKey
        {
        public:
            typedef ObjectWithPropertyKey Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(PropertyChange,ObjectWithPropertyKey,IPropertyChange,IObjectWithPropertyKey)

            PropertyChange& ApplyToPropVariant( REFPROPVARIANT propvarIn, PROPVARIANT *ppropvarOut)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->ApplyToPropVariant( propvarIn, ppropvarOut);
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
            PropertyChange& ApplyToPropVariant( REFPROPVARIANT propvarIn, PROPVARIANT& propvarOut)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->ApplyToPropVariant( propvarIn, &propvarOut);
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
        
        };


        class PropertyChangeArray : public Unknown
        {
        public:
            typedef Unknown Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(PropertyChangeArray,Unknown,IPropertyChangeArray,IUnknown)

            UINT GetCount( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                UINT result = 0;
                auto hr = pInterface->GetCount( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
        
            template< typename T>
            T GetAt( UINT iIndex )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                T::InterfaceType* result = nullptr;
                auto hr = pInterface->GetAt(iIndex, __uuidof(T::InterfaceType),(void**) &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
        
            PropertyChangeArray& InsertAt( UINT iIndex, IPropertyChange *ppropChange)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->InsertAt(iIndex, ppropChange );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
        
            PropertyChangeArray& Append(IPropertyChange *ppropChange)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->Append( ppropChange );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
        
            PropertyChangeArray& AppendOrReplace( IPropertyChange *ppropChange)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->AppendOrReplace( ppropChange );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
        
            PropertyChangeArray& RemoveAt( UINT iIndex )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->RemoveAt( iIndex );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
        
            bool IsKeyInArray(REFPROPERTYKEY key)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->IsKeyInArray( key );
                
                return hr == S_OK;
            }
        
        };


        class PropertyStoreCapabilities : public Unknown
        {
        public:
            typedef Unknown Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(PropertyStoreCapabilities,Unknown,IPropertyStoreCapabilities,IUnknown)

            bool IsPropertyWritable( REFPROPERTYKEY key )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->IsPropertyWritable( key );
                
                return hr == S_OK;
            }
        };


        class PropertyStoreCache : public PropertyStore
        {
        public:
            typedef PropertyStore Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(PropertyStoreCache,PropertyStore,IPropertyStoreCache,IPropertyStore)

            PSC_STATE GetState( REFPROPERTYKEY key )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                PSC_STATE result;
                auto hr = pInterface->GetState( key, &result);
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
            PropertyStoreCache& GetValueAndState( REFPROPERTYKEY key, PROPVARIANT *ppropvar, PSC_STATE *pstate)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->GetValueAndState( key, ppropvar, pstate );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }

            PropertyStoreCache& SetState( REFPROPERTYKEY key, PSC_STATE state)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->SetState( key, state );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
        
            PropertyStoreCache& SetValueAndState( REFPROPERTYKEY key, const PROPVARIANT *ppropvar, PSC_STATE state)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->SetValueAndState( key, ppropvar, state);
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
        
        };


        class PropertyEnumType : public Unknown
        {
        public:
            typedef Unknown Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(PropertyEnumType,Unknown,IPropertyEnumType,IUnknown)

            PROPENUMTYPE GetEnumType( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                PROPENUMTYPE result = PET_DISCRETEVALUE;
                auto hr = pInterface->GetEnumType( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
        
            PropertyVariant GetValue( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                PropertyVariant result;
                auto hr = pInterface->GetValue( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
        
            PropertyVariant GetRangeMinValue( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                PropertyVariant result;
                auto hr = pInterface->GetRangeMinValue( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
            PropertyVariant GetRangeSetValue( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                PropertyVariant result;
                auto hr = pInterface->GetRangeSetValue( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
        
            String GetDisplayText( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                LPWSTR result;
                auto hr = pInterface->GetDisplayText( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                String s(result);
                CoTaskMemFree(result);
                return s;
            }
        
        };


        class PropertyEnumType2 : public PropertyEnumType
        {
        public:
            typedef PropertyEnumType Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(PropertyEnumType2,PropertyEnumType,IPropertyEnumType2,IPropertyEnumType)

            String GetImageReference( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                LPWSTR result;
                auto hr = pInterface->GetImageReference( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                String s(result);
                CoTaskMemFree(result);
                return s;
            }
        };


        class PropertyEnumTypeList : public Unknown
        {
        public:
            typedef Unknown Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(PropertyEnumTypeList,Unknown,IPropertyEnumTypeList,IUnknown)

            UINT GetCount( );
        
            template <typename T >
            T GetAt( UINT itype )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                T::InterfaceType* result;
                auto hr = pInterface->GetAt(itype, __uuidof(T::InterfaceType), (void**) &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return T(result);
            }

            PropertyEnumType GetAt( UINT itype )
            {
                HWIN_TRACE();
                return GetAt<PropertyEnumType>(itype);
            }

        
            UINT FindMatchingIndex( REFPROPVARIANT propvarCmp)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                UINT result = 0;
                auto hr = pInterface->FindMatchingIndex(propvarCmp, &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
        };


        class PropertyDescription : public Unknown
        {
        public:
            typedef Unknown Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(PropertyDescription,Unknown,IPropertyDescription,IUnknown)

            PROPERTYKEY GetPropertyKey( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                PROPERTYKEY result;
                auto hr = pInterface->GetPropertyKey( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
        
            String GetCanonicalName( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                LPWSTR result;
                auto hr = pInterface->GetCanonicalName( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                String s(result);
                CoTaskMemFree(result);
                return s;
            }
        
            VariantType GetPropertyType( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                VARTYPE result;
                auto hr = pInterface->GetPropertyType( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return VariantType(result);
            }
        
            String GetDisplayName( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                LPWSTR result;
                auto hr = pInterface->GetDisplayName( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                String s(result);
                CoTaskMemFree(result);
                return s;
            }
        
            String GetEditInvitation( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                LPWSTR result;
                auto hr = pInterface->GetEditInvitation( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                String s(result);
                CoTaskMemFree(result);
                return s;
            }
        
            PROPDESC_TYPE_FLAGS GetTypeFlags( PROPDESC_TYPE_FLAGS mask)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                PROPDESC_TYPE_FLAGS result;
                auto hr = pInterface->GetTypeFlags( mask,&result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
            PROPDESC_VIEW_FLAGS GetViewFlags( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                PROPDESC_VIEW_FLAGS result;
                auto hr = pInterface->GetViewFlags( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
        
            UINT GetDefaultColumnWidth( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                UINT result;
                auto hr = pInterface->GetDefaultColumnWidth( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }

            PROPDESC_DISPLAYTYPE GetDisplayType( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                PROPDESC_DISPLAYTYPE result;
                auto hr = pInterface->GetDisplayType( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
        
            SHCOLSTATEF GetColumnState( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                SHCOLSTATEF result;
                auto hr = pInterface->GetColumnState( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
        
            PROPDESC_GROUPING_RANGE GetGroupingRange( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                PROPDESC_GROUPING_RANGE result;
                auto hr = pInterface->GetGroupingRange( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }

            PROPDESC_RELATIVEDESCRIPTION_TYPE GetRelativeDescriptionType( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                PROPDESC_RELATIVEDESCRIPTION_TYPE result;
                auto hr = pInterface->GetRelativeDescriptionType( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
        
            PropertyDescription& GetRelativeDescription( REFPROPVARIANT propvar1, REFPROPVARIANT propvar2,String& desc1,String& desc2)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                LPWSTR pDesc1, pDesc2;
                auto hr = pInterface->GetRelativeDescription(propvar1, propvar2, &pDesc1, &pDesc2 );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                desc1 = String(pDesc1);
                desc2 = String(pDesc2);
                CoTaskMemFree(pDesc1);
                CoTaskMemFree(pDesc2);
                return *this;
            }

            PROPDESC_SORTDESCRIPTION GetSortDescription( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                PROPDESC_SORTDESCRIPTION result;
                auto hr = pInterface->GetSortDescription( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }

            String GetSortDescriptionLabel( bool descending )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                LPWSTR result;
                auto hr = pInterface->GetSortDescriptionLabel(descending , &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                String s(result);
                CoTaskMemFree(result);
                return s;
            }
        
            PROPDESC_AGGREGATION_TYPE GetAggregationType( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                PROPDESC_AGGREGATION_TYPE result;
                auto hr = pInterface->GetAggregationType( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
        
            PropertyDescription& GetConditionType( PROPDESC_CONDITION_TYPE *pcontype,CONDITION_OPERATION *popDefault)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->GetConditionType( pcontype,popDefault);
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }

            PropertyDescription& GetConditionType( PROPDESC_CONDITION_TYPE& contype,CONDITION_OPERATION& opDefault)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->GetConditionType( &contype,&opDefault);
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
        
            template < typename T >
            T GetEnumTypeList( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                T::InterfaceType* result;
                auto hr = pInterface->GetEnumTypeList(__uuidof(T::InterfaceType), (void**)&result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return T(result);
            }

            PropertyEnumTypeList GetAt( UINT itype )
            {
                HWIN_TRACE();
                return GetEnumTypeList<PropertyEnumTypeList>( );
            }

        
            PropertyVariant CoerceToCanonicalValue( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                PropertyVariant result;
                auto hr = pInterface->CoerceToCanonicalValue( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
            String FormatForDisplay(REFPROPVARIANT propvar, PROPDESC_FORMAT_FLAGS pdfFlags)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                LPWSTR result;
                auto hr = pInterface->FormatForDisplay(propvar, pdfFlags , &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                String s(result);
                CoTaskMemFree(result);
                return s;
            }
        
            bool IsValueCanonical( REFPROPVARIANT propvar)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->IsValueCanonical( propvar );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return hr == S_OK;
            }
        };

        class PropertyDescriptionList : public Unknown
        {
        public:
            typedef Unknown Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(PropertyDescriptionList,Unknown,IPropertyDescriptionList,IUnknown)

            UINT GetCount( );
        
            template<typename T >
            T GetAt( UINT iElem)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                T::InterfaceType* result;
                auto hr = pInterface->GetAt(iElem,__uuidof(T::InterfaceType), (void**)&result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return T(result);
            }

            PropertyDescription GetAt( UINT iElem)
            {
                HWIN_TRACE();
                return GetAt<PropertyDescription>(iElem);
            }

        };


        class PropertyDescription2 : public PropertyDescription
        {
        public:
            typedef PropertyDescription Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(PropertyDescription2,PropertyDescription,IPropertyDescription2,IPropertyDescription)

            String GetImageReferenceForValue(REFPROPVARIANT propvar )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                LPWSTR result;
                auto hr = pInterface->GetImageReferenceForValue(propvar,&result);
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                String s(result);
                CoTaskMemFree(result);
                return s;
            }
        };

        class PropertyDescriptionAliasInfo : public PropertyDescription
        {
        public:
            typedef PropertyDescription Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(PropertyDescriptionAliasInfo,PropertyDescription,IPropertyDescriptionAliasInfo,IPropertyDescription)

            template <typename T >
            T GetSortByAlias( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                T::InterfaceType* result;
                auto hr = pInterface->GetSortByAlias(__uuidof(T::InterfaceType), (void**)&result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return T(result);
            }
        
            PropertyDescription GetSortByAlias( )
            {
                HWIN_TRACE();
                return GetSortByAlias<PropertyDescription>();
            }

            template <typename T >
            T GetAdditionalSortByAliases( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                T::InterfaceType* result;
                auto hr = pInterface->GetAdditionalSortByAliases(__uuidof(T::InterfaceType), (void**)&result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return T(result);
            }
            
            PropertyDescriptionList GetAdditionalSortByAliases( )
            {
                HWIN_TRACE();
                return GetAdditionalSortByAliases<PropertyDescriptionList>();
            }

        };


        class PropertyDescriptionSearchInfo : public PropertyDescription
        {
        public:
            typedef PropertyDescription Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(PropertyDescriptionSearchInfo,PropertyDescription,IPropertyDescriptionSearchInfo,IPropertyDescription)

            PROPDESC_SEARCHINFO_FLAGS GetSearchInfoFlags( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                PROPDESC_SEARCHINFO_FLAGS result;
                auto hr = pInterface->GetSearchInfoFlags( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
        
            PROPDESC_COLUMNINDEX_TYPE GetColumnIndexType( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                PROPDESC_COLUMNINDEX_TYPE result;
                auto hr = pInterface->GetColumnIndexType( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
        
            String GetProjectionString( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                LPWSTR result;
                auto hr = pInterface->GetProjectionString(&result);
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                String s(result);
                CoTaskMemFree(result);
                return s;
            }
        
            UINT GetMaxSize( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                UINT result;
                auto hr = pInterface->GetMaxSize( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
        
        };


        class PropertyDescriptionRelatedPropertyInfo : public PropertyDescription
        {
        public:
            typedef PropertyDescription Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(PropertyDescriptionRelatedPropertyInfo,PropertyDescription,IPropertyDescriptionRelatedPropertyInfo,IPropertyDescription)

            template <typename T >
            T GetRelatedProperty( LPCWSTR pszRelationshipName )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                T::InterfaceType* result;
                auto hr = pInterface->GetRelatedProperty(pszRelationshipName,__uuidof(T::InterfaceType), (void**)&result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return T(result);
            }
        
            PropertyDescription GetRelatedProperty( LPCWSTR pszRelationshipName )
            {
                HWIN_TRACE();
                return GetRelatedProperty<PropertyDescription>(pszRelationshipName);
            }

        };


        class PropertySystem : public Unknown
        {
        public:
            typedef Unknown Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(PropertySystem,Unknown,IPropertySystem,IUnknown)

            template <typename T >
            T GetPropertyDescription( REFPROPERTYKEY propkey)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                T::InterfaceType* result;
                auto hr = pInterface->GetPropertyDescription(propkey,__uuidof(T::InterfaceType), (void**)&result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return T(result);
            }

            PropertyDescription GetPropertyDescription( REFPROPERTYKEY propkey)
            {
                HWIN_TRACE();
                return GetPropertyDescription<PropertyDescription>(propkey);
            }


            template <typename T >
            T GetPropertyDescriptionByName( LPCWSTR pszCanonicalName)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                T::InterfaceType* result;
                auto hr = pInterface->GetPropertyDescriptionByName(pszCanonicalName,__uuidof(T::InterfaceType), (void**)&result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return T(result);
            }

            PropertyDescription GetPropertyDescriptionByName( LPCWSTR pszCanonicalName)
            {
                HWIN_TRACE();
                return GetPropertyDescriptionByName<PropertyDescription>(pszCanonicalName);
            }


            template <typename T >
            T GetPropertyDescriptionListFromString( LPCWSTR pszPropList)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                T::InterfaceType* result;
                auto hr = pInterface->GetPropertyDescriptionListFromString(pszPropList,__uuidof(T::InterfaceType), (void**)&result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return T(result);
            }

            PropertyDescriptionList GetPropertyDescriptionListFromString( LPCWSTR pszPropList)
            {
                HWIN_TRACE();
                return GetPropertyDescriptionListFromString<PropertyDescriptionList>(pszPropList);
            }
        
            template <typename T >
            T EnumeratePropertyDescriptions( PROPDESC_ENUMFILTER filterOn)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                T::InterfaceType* result;
                auto hr = pInterface->EnumeratePropertyDescriptions(filterOn,__uuidof(T::InterfaceType), (void**)&result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return T(result);
            }

            PropertyDescriptionList EnumeratePropertyDescriptions( PROPDESC_ENUMFILTER filterOn)
            {
                HWIN_TRACE();
                return EnumeratePropertyDescriptions<PropertyDescriptionList>(filterOn);
            }

        
            PropertySystem& FormatForDisplay(  REFPROPERTYKEY key,REFPROPVARIANT propvar,PROPDESC_FORMAT_FLAGS pdff,LPWSTR pszText,DWORD cchText)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                
                auto hr = pInterface->FormatForDisplay(key,propvar,pdff,pszText,cchText);
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
        
            String FormatForDisplayAlloc( REFPROPERTYKEY key, REFPROPVARIANT propvar, PROPDESC_FORMAT_FLAGS pdff)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                LPWSTR result;
                auto hr = pInterface->FormatForDisplayAlloc(key, propvar, pdff,&result);
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                String s(result);
                CoTaskMemFree(result);
                return s;
            }
        
            PropertySystem& RegisterPropertySchema(LPCWSTR pszPath)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                
                auto hr = pInterface->RegisterPropertySchema(pszPath);
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }

            PropertySystem& UnregisterPropertySchema(LPCWSTR pszPath)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                
                auto hr = pInterface->UnregisterPropertySchema(pszPath);
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
        
            PropertySystem& RefreshPropertySchema( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->RefreshPropertySchema( );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
        };


        class PropertyStoreFactory : public Unknown
        {
        public:
            typedef Unknown Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(PropertyStoreFactory,Unknown,IPropertyStoreFactory,IUnknown)

            template <typename T >
            T GetPropertyStore( GETPROPERTYSTOREFLAGS flags, IUnknown *pUnkFactory)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                T::InterfaceType* result;
                auto hr = pInterface->GetPropertyStore(flags, pUnkFactory,__uuidof(T::InterfaceType), (void**)&result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return T(result);
            }

            PropertyStore GetPropertyStore( GETPROPERTYSTOREFLAGS flags, IUnknown *pUnkFactory)
            {
                HWIN_TRACE();
                return GetPropertyStore<PropertyStore>( flags, pUnkFactory);
            }
        
            template <typename T >
            T GetPropertyStoreForKeys( const PROPERTYKEY *rgKeys, UINT cKeys, GETPROPERTYSTOREFLAGS flags)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                T::InterfaceType* result;
                auto hr = pInterface->GetPropertyStoreForKeys(rgKeys, cKeys, flags,__uuidof(T::InterfaceType), (void**)&result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return T(result);
            }
            PropertyStore GetPropertyStoreForKeys( const PROPERTYKEY *rgKeys, UINT cKeys, GETPROPERTYSTOREFLAGS flags)
            {
                HWIN_TRACE();
                return GetPropertyStoreForKeys<PropertyStore>( rgKeys, cKeys, flags);
            }


        };


        class DelayedPropertyStoreFactory : public PropertyStoreFactory
        {
        public:
            typedef PropertyStoreFactory Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(DelayedPropertyStoreFactory,PropertyStoreFactory,IDelayedPropertyStoreFactory,IPropertyStoreFactory)

            template <typename T >
            T GetDelayedPropertyStore( GETPROPERTYSTOREFLAGS flags, DWORD dwStoreId)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                T::InterfaceType* result;
                auto hr = pInterface->GetDelayedPropertyStore(flags, dwStoreId,__uuidof(T::InterfaceType), (void**)&result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return T(result);
            }

            

            PropertyStore GetDelayedPropertyStore( GETPROPERTYSTOREFLAGS flags, DWORD dwStoreId)
            {
                HWIN_TRACE();
                return GetDelayedPropertyStore<PropertyStore>( flags, dwStoreId);
            }
        };


        class PersistSerializedPropStorage : public Unknown
        {
        public:
            typedef Unknown Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(PersistSerializedPropStorage,Unknown,IPersistSerializedPropStorage,IUnknown)

            PersistSerializedPropStorage& SetFlags( PERSIST_SPROPSTORE_FLAGS flags)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->SetFlags( flags );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
        
            PersistSerializedPropStorage& SetPropertyStorage( PCUSERIALIZEDPROPSTORAGE psps,DWORD cb)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->SetPropertyStorage( psps,cb );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }

            PersistSerializedPropStorage& GetPropertyStorage( SERIALIZEDPROPSTORAGE **ppsps,DWORD *pcb)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->GetPropertyStorage( ppsps,pcb );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
        };


        class PersistSerializedPropStorage2 : public PersistSerializedPropStorage
        {
        public:
            typedef PersistSerializedPropStorage Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(PersistSerializedPropStorage2, PersistSerializedPropStorage,IPersistSerializedPropStorage2,IPersistSerializedPropStorage)

            DWORD GetPropertyStorageSize( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                DWORD result;
                auto hr = pInterface->GetPropertyStorageSize( &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
        
            DWORD GetPropertyStorageBuffer( SERIALIZEDPROPSTORAGE *psps, DWORD cb)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                DWORD result;
                auto hr = pInterface->GetPropertyStorageBuffer(psps, cb, &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return result;
            }
        };


        class PropertySystemChangeNotify : public Unknown
        {
        public:
            typedef Unknown Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(PropertySystemChangeNotify,Unknown,IPropertySystemChangeNotify,IUnknown)

            PropertySystemChangeNotify& SchemaRefreshed( )
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                auto hr = pInterface->SchemaRefreshed();
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return *this;
            }
        };


        class CreateObject_ : public Unknown
        {
        public:
            typedef Unknown Base;
            HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(CreateObject_,Unknown,ICreateObject,IUnknown)

            template <typename T >
            T CreateObject( REFCLSID clsid, IUnknown *pUnkOuter = nullptr)
            {
                HWIN_TRACE();
                auto pInterface = GetInterface();
                T::InterfaceType* result;
                auto hr = pInterface->CreateObject( clsid, pUnkOuter,__uuidof(T::InterfaceType), &result );
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
                return T(result);
            }
        
        };




    };
};

#endif //__HWINPROPSYS_H__
